/*
* Hua-Xia Form Validator(Base on Prototype 1.5 && Refers to Andrew Tetlaw's "Really easy field validation with Prototype")
* Author TrueOrFalse.Yuan
* Version 1.0
* Date 2007-07-10
*/
var rule = Class.create();
rule.prototype = {
    initialize : function(ruleName,error,validate) {
        if(typeof validate == 'function'){
			this.refMethods = $H();
			this._validate = validate;
		} else {
			this.refMethods = $H(validate);
			this._validate = function(){
			    return true
			};
		}
		this.ruleName = ruleName;
		this.error = error;
	},
    validate : function(value,element) {
		return (this._validate(value,element) && this.refMethods.all(function(refMethod){
			return rule.methods[refMethod.key] ? rule.methods[refMethod.key](value,refMethod.value) : true;
		}));
	}
}

rule.methods = {
	pattern : function(value,option) {
	    return  ((value == null) || (value.length == 0)) || option.test(value);
	},
	minLength : function(value,option) {
	    return value.length >= option
	},
	maxLength : function(value,option) {
	    return value.length <= option
	},
	min : function(value,option) {
	    return value >= parseFloat(option)
	}, 
	max : function(value,option) {
	    return value <= parseFloat(option)
	},
	notOneOf : function(value,option) {
	    return $A(option).any(function(value) {
		    return value != value;
		})
	},
	oneOf : function(value,option) {
	    return $A(option).any(function(value) {
		    return value == value;
		})
	},
	is : function(value,option) {
	    return value == option
	},
	isNot : function(value,option) {
	    return value != option
	},
	equalToField : function(value,option) {
	    return value == $F(option)
	},
	notEqualToField : function(value,option) {
	    return value != $F(option)
	},
	lessToField : function(value,option) {
	    return parseInt(value) < parseInt($F(option))
	},
	largerToField : function(value,option) {
	    return parseInt(value) > parseInt($F(option))
	},
	lessOrEqualToField : function(value,option) {
	    return parseInt(value) <= parseInt($F(option))
	},
	largerOrEqualToField : function(value,option) {
	    return parseInt(value) >= parseInt($F(option))
	},
	include : function(value,option) {
	    return value.indexOf(option) != -1;
	},
	notInclude : function(value,option) {
	    return value.indexOf(option) == -1;	
	}
}

var hxvalidator = Class.create();
hxvalidator.prototype = {
    initialize : function(form, options){
    	this.options = Object.extend({
    		validateType : 'ON_USER_TRIGGER',
    		
    		isStopOnFirst : false,
    		isFocusOnError : true,
    		
    		messageAppender : function(element, message) {
    		    alert(message);
    		},
    		messageRemover : function(element) {
    		
    		}
    	}, options || {});
    	this.form = $(form);
        
        var appender = this.options.messageAppender;
        var remover = this.options.messageRemover;
    	if(this.options.validateType == 'ON_ELEMENT_LOSTFOCUS'){
    	    Form.getElements(this.form).each(function(obj) {
    	        Event.observe(obj, 'blur',function(evt) {
    	            hxvalidator.e_validate(Event.element(evt),{messageAppender : appender, messageRemover : remover});
    	        });
    	    });
    	} else if(this.options.validateType == 'ON_FORM_SUBMIT'){
    	    Event.observe(this.form,'submit',this.f_submit.bind(this));
    	}
    },
	f_submit :  function(evt){
		if(!this.validate()) Event.stop(evt);
	},
    validate : function(){
    
        var result = false;        
        var appender = this.options.messageAppender;
        var remover = this.options.messageRemover;  
        
        if(this.options.isStopOnFirst) {              
        	result = Form.getElements(this.form).all(function(element){        		
        	    return hxvalidator.e_validate(element,{messageAppender : appender, messageRemover : remover}); 
        	});
        } else {           
        	result = Form.getElements(this.form).collect(function(element){        	   
        	    return hxvalidator.e_validate(element,{messageAppender : appender, messageRemover : remover}); 
        	}).all();        	 
        }
        
        if(!result && this.options.isFocusOnError) {
            try{
            	Form.getElements(this.form).findAll(function(element){
            	    return $(element).hasClassName('validation-failed');
            	}).first().focus();
            } catch(e){}
        }
        
        return result;
    }
}

Object.extend(hxvalidator, {
    e_validate : function(element,msgHandler){
        element = $(element);
        var rulenames = element.classNames();
        return result = rulenames.all(function(rulename) {
        	return hxvalidator.test(rulename,element,msgHandler);
        });
    },
    test : function(ruleName,element,msgHandler){
        var rule = hxvalidator.getRule(ruleName);
        
        var appender = msgHandler.messageAppender;
        var remover = msgHandler.messageRemover;
        try {
            if(hxvalidator.isVisible(element)){
                if(!rule.validate($F(element),element)) {
        			element.removeClassName('validation-passed');
        			element.addClassName('validation-failed');
        			
                    var propertyname = hxvalidator.getPropertyName(element);
                    var errormessage = "[ " + propertyname + " ] " + ((element && element.title) ? element.title : rule.error);
        			appender(element, errormessage);
    			
    			    return false;
    			} else {
        			element.removeClassName('validation-failed');
        			element.addClassName('validation-passed');
        			
        			remover(element);
        			
        			return true;
    			}
            } else {
    			element.removeClassName('validation-failed');
    			element.removeClassName('validation-passed');
    			
    			remover(element);
    			return true;
            }
        } catch(e) {
			throw(e)
		}
    }
});

Object.extend(hxvalidator, {
	rules : {
		'_Empty_' : new rule('_Empty_','',{})
	},
	addRule : function(ruleName, error, validate) {
		var rule_add = {};
		rule_add[ruleName] = new rule(ruleName, error, validate);
		Object.extend(hxvalidator.rules, rule_add);
	},
	getRule : function(ruleName){
	    return  hxvalidator.rules[ruleName] ? hxvalidator.rules[ruleName] : hxvalidator.rules['_Empty_'];
	}
});

Object.extend(hxvalidator, {
	isVisible : function(element) {
	    element = $(element);
		while(element.tagName != 'BODY') {
		    try{
    			if(!element.visible()){
    			    return false;
    			}
			} catch(e) {}
			element = element.parentNode;
		}
		return true;
	},
	getPropertyName : function(element) {
	    element = $(element);
	    var propertyname = element.readAttribute('property');
	    if(propertyname == null) {
            propertyname = "!" + element.name + "!";
        }
        return propertyname;
	}
});

hxvalidator.addRule('empty', '', function(value) {
    return ((value == null) || (value.length == 0) || (/^[ ]+$/.test(value)));
});

hxvalidator.addRule('required', '此项为必填项!', function(value) {
    return !hxvalidator.getRule('empty').validate(value);
});

hxvalidator.addRule('validate-chinese', '请输入中文!', function(value) {
	return hxvalidator.getRule('empty').validate(value) || /^[\u4e00-\u9fa5]+$/.test(value);
});//Please enter a valid number in this field.

hxvalidator.addRule('validate-number', '请输入数字!', function(value) {
	return hxvalidator.getRule('empty').validate(value) || (!isNaN(value) && !/^\s+$/.test(value));
});//Please enter a valid number in this field.

hxvalidator.addRule('validate-digits', '请输入整数!', function(value) {
    return hxvalidator.getRule('empty').validate(value) ||  !/[^\d]/.test(value);
});//Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.
			
hxvalidator.addRule('validate-alpha', '请输入英文字母!', function (value) {
	return hxvalidator.getRule('empty').validate(value) ||  /^[a-zA-Z]+$/.test(value);
});//Please use letters only (a-z) in this field.
			
hxvalidator.addRule('validate-alphanum', '请输入英文字母或数字!', function(value) {
	return hxvalidator.getRule('empty').validate(value) ||  !/\W/.test(value);
});//Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.
				
hxvalidator.addRule('validate-email', '请按正确格式输入E-Mail!', function (value) {
	return hxvalidator.getRule('empty').validate(value) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(value);
});//Please enter a valid email address. For example fred@domain.com .
			
hxvalidator.addRule('validate-url', '请按正确格式输入URL地址!', function (value) {
	return hxvalidator.getRule('empty').validate(value) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(value);
});//Please enter a valid URL.

hxvalidator.addRule('validate-date', '请按正确格式输入日期!', function(value) {
	var date = new Date(value);
	return hxvalidator.getRule('empty').validate(value) || !isNaN(date);
});//Please enter a valid date.
			
hxvalidator.addRule('validate-date-cn', '请按正确格式输入日期!', function(value) {
	if(hxvalidator.getRule('empty').validate(value)){
	    return true;
	}
	var regex = /^(\d{4})-(\d{2})-(\d{2})$/;
	if(!regex.test(value)){
	    return false;
	}
	var d = new Date(value.replace(regex, '$1/$2/$3'));
	return (parseInt(RegExp.$2, 10) == (1 + d.getMonth())) && 
				(parseInt(RegExp.$3, 10) == d.getDate()) && 
				(parseInt(RegExp.$1, 10) == d.getFullYear());
});//Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.
			
hxvalidator.addRule('validate-currency-dollar', '', function(value) {
	return hxvalidator.getRule('empty').validate(value) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(value)
});//Please enter a valid $ amount. For example $100.00 .
			
hxvalidator.addRule('validate-selection', '请选择!', function(value,element){
	return element.options ? element.selectedIndex > 0 : !hxvalidator.getRule('empty').validate(value);
});//Please make a selection
			
hxvalidator.addRule('validate-one-required', '请选择一项!', function(value,element){
	var pn = element.parentNode;
	var options = pn.getElementsByTagName('INPUT');
	return $A(options).any(function(element) {
		return $F(element);
	});
});//Please select one of the above options.

hxvalidator.addRule('validate-expression', '必须由英文字母、数字及下划线组成, 且首字母必须是英文字符!', { pattern : /^[a-zA-Z][0-9a-zA-Z\_]*$/ });

hxvalidator.addRule('validate-oid', '请按正确格式输入OID!', function(value) {
	if(hxvalidator.getRule('empty').validate(value)){
	    return true;
	}
	var regex = /^\d(.\d+)*.\d+$|^\d+$/;
	if(!regex.test(value)){
	    return false;
	}
	return true;
});

hxvalidator.addRule('validate-zero', '不能输入为0的数值!', function(value) {
	if(hxvalidator.getRule('empty').validate(value)){
	    return true;
	}	
	if(parseInt(value) == 0){		
	    return false;
	}
	return true;
});

hxvalidator.addRule('validate-ip-pattern', '请输入正确格式的IP地址!', function(value) {
	return hxvalidator.getRule('empty').validate(value) || /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(value)
});
